package mathsys2;

import java.util.Objects;

/**
 * 算式抽象类：提取加法、减法算式的共性属性与约束，定义抽象方法规范子类行为
 * 核心职责：
 * 1. 封装共性属性（运算数、运算符、结果）；
 * 2. 统一基础约束校验（运算数0-100、仅支持+/-）；
 * 3. 定义抽象方法（结果计算、重复判定），由子类实现差异化逻辑；
 * 4. 提供通用方法（getter、toString、hashCode基础实现）。
 */
public abstract class AbstractArithmetic {
    // -------------------------- 共性属性（私有，遵循封装原则） --------------------------
    private final int num1;       // 第一个运算数（0-100，实验核心约束）
    private final int num2;       // 第二个运算数（0-100，实验核心约束）
    private final char operator;  // 运算符（仅支持'+'或'-'，实验核心约束）
    protected int result;         // 运算结果（子类需通过calculate()赋值，protected允许子类访问）


    // -------------------------- 构造方法（统一基础约束校验） --------------------------
    /**
     * 抽象类构造方法：仅被子类调用，完成共性约束校验
     * @param num1 第一个运算数（0-100）
     * @param num2 第二个运算数（0-100）
     * @param operator 运算符（'+'或'-'）
     * @throws IllegalArgumentException 当参数违反实验约束时抛出
     */
    public AbstractArithmetic(int num1, int num2, char operator) {
        // 1. 校验运算数范围（0-100，实验“100以内运算”约束）
        validateNumberRange(num1, "num1");
        validateNumberRange(num2, "num2");

        // 2. 校验运算符合法性（仅支持+/-，实验约束）
        validateOperator(operator);

        // 3. 初始化共性属性
        this.num1 = num1;
        this.num2 = num2;
        this.operator = operator;

        // 4. 调用抽象方法计算结果（子类实现具体逻辑，确保初始化时完成结果计算）
        this.calculate();
    }


    // -------------------------- 共性约束校验方法（私有，仅抽象类内部调用） --------------------------
    /**
     * 校验运算数是否在0-100范围内（实验核心约束）
     * @param num 待校验的运算数
     * @param paramName 运算数参数名（用于异常提示，提升调试效率）
     * @throws IllegalArgumentException 当运算数超出范围时抛出
     */
    private void validateNumberRange(int num, String paramName) {
        if (num < 0 || num > 100) {
            throw new IllegalArgumentException("运算数必须在0-100之间（实验约束）：" + paramName + "=" + num);
        }
    }

    /**
     * 校验运算符是否合法（仅支持'+'或'-'，实验约束）
     * @param operator 待校验的运算符
     * @throws IllegalArgumentException 当运算符无效时抛出
     */
    private void validateOperator(char operator) {
        if (operator != '+' && operator != '-') {
            throw new IllegalArgumentException("仅支持 '+' 和 '-' 运算符（实验约束）：当前运算符为'" + operator + "'");
        }
    }


    // -------------------------- 抽象方法（子类需实现差异化逻辑） --------------------------
    /**
     * 抽象方法：计算运算结果（加法/减法逻辑不同，由子类实现）
     * 实验要求：加法和≤100，减法差≥0
     */
    public abstract void calculate();

    /**
     * 抽象方法：判断两个算式是否重复（加法需处理交换律，减法严格匹配，由子类实现）
     * 实验要求：加法a+b与b+a视为重复，减法a-b与b-a视为不同
     * @param obj 待比较的对象
     * @return true=重复，false=不重复
     */
    @Override
    public abstract boolean equals(Object obj);


    // -------------------------- 通用方法（共性实现，子类可直接使用） --------------------------
    /**
     * 格式化算式字符串（如“3 + 5 = ?”，实验“格式化显示”需求）
     * @return 标准化算式字符串
     */
    @Override
    public String toString() {
        return num1 + " " + operator + " " + num2 + " = ?";
    }

    /**
     * 基础hashCode实现（子类可重写，确保与equals逻辑一致）
     * 实验用途：配合集合（如HashSet）实现去重
     * @return 哈希值
     */
    @Override
    public int hashCode() {
        return Objects.hash(num1, num2, operator);
    }

    // Getter方法（对外暴露必要属性，遵循封装原则，实验“习题类访问算式属性”需求）
    public int getNum1() {
        return num1;
    }

    public int getNum2() {
        return num2;
    }

    public char getOperator() {
        return operator;
    }

    public int getResult() {
        return result;
    }
}
